package com.kehutong.payfees.syn;

import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;


public class Locks {
	
	private static ConcurrentMap<Object, Object> lockMap;
	
	static {
		lockMap = new ConcurrentHashMap<Object, Object>();
	}
	
	public static void exeSyn(Object param, CallBackNoReturn call) throws Exception {
		try {
			Object lock = getLock(lockMap, param);
			synchronized (lock) {
				call.call();
			}
		} finally {
			lockMap.remove(param);
		}
	}

	public static void exeSyn(Object param, CallBackNoReturnNoExeption call) {
		try {
			Object lock = getLock(lockMap, param);
			synchronized (lock) {
				call.call();
			}
		} finally {
			lockMap.remove(param);
		}
	}
	
	public static <T> T exeSyn(Object param, CallBackReturn<T> call) throws Exception {
		try {
			Object lock = getLock(lockMap, param);
			synchronized (lock) {
				return call.call();
			}
		} finally {
			lockMap.remove(param);
		}
	}
	
	public static <T> T exeSyn(Object param, CallBackReturnNoException<T> call) {
		try {
			Object lock = getLock(lockMap, param);
			synchronized (lock) {
				return call.call();
			}
		} finally {
			lockMap.remove(param);
		}
	}
	
	private static Object getLock(ConcurrentMap<Object, Object> lockMap, Object key) {
		Object lock = lockMap.get(key);
		if (Objects.nonNull(lock)) {
			return lock;
		}
		
		Object old = lockMap.putIfAbsent(key, lock = new Object());
		if (Objects.nonNull(old)) {
			return old;
		}
		
		return lock;
		
	}

}
